package com.ssy.lingxi.contract.serviceimpl;

import com.ssy.lingxi.contract.entity.SignatureAccount;
import com.ssy.lingxi.contract.esign.api.SignApi;
import com.ssy.lingxi.contract.esign.constant.EsignApiCode;
import com.ssy.lingxi.contract.esign.constant.EsignConstants;
import com.ssy.lingxi.contract.esign.exception.EsignException;
import com.ssy.lingxi.contract.esign.request.PersonalAccountCreateRequest;
import com.ssy.lingxi.contract.esign.request.PersonalAccountUpdateRequest;
import com.ssy.lingxi.contract.esign.request.PersonalSealCreateRequest;
import com.ssy.lingxi.contract.esign.response.*;
import com.ssy.lingxi.contract.model.constant.CommonBooleanEnum;
import com.ssy.lingxi.contract.repository.SignatureAccountRepository;
import com.ssy.lingxi.contract.service.ISignatureAccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.Optional;

/**
 * 签章个人信息服务实现类
 * @author yzc
 * @version 2.0.0
 * @date 2020/9/1
 */
@Slf4j
@Service
public class SignatureAccountServiceImpl implements ISignatureAccountService {

    @Resource
    private SignatureAccountRepository signatureAccountRepository;
    @Resource
    private SignApi signApi;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String createAccount(String idNumber, String name, String mobile) throws EsignException {
        // 查询系统是否留存账户信息
        SignatureAccount account = signatureAccountRepository.findByIdNumber(idNumber);
        if (Objects.nonNull(account)) {
            // 校验信息是否一致
            if (!verifyMessage(account, name, mobile)) {
                // 修改账号信息,如果已实名,将会变成未实名
                PersonalAccountUpdateRequest updateAccountRequest = PersonalAccountUpdateRequest.builder()
                        .accountId(account.getAccountId())
                        .name(name)
                        .mobile(mobile)
                        .build();
                PersonalAccountUpdateResponse updateAccountResponse = signApi.account().personalAccountUpdate(updateAccountRequest);

                // 更新留存信息
                account.setName(updateAccountResponse.getName());
                account.setMobile(updateAccountResponse.getMobile());
                account.setState(CommonBooleanEnum.NO.getCode());
                account.setSilent(CommonBooleanEnum.NO.getCode());

            }

            // 返回个人账户id
            return account.getAccountId();
        }

        SignatureAccount signatureAccount = createAccountIfAbsent(idNumber, name, mobile);
        signatureAccountRepository.saveAndFlush(signatureAccount);

        return signatureAccount.getAccountId();
    }

    /**
     * 如果存在账号则更新, 不存在则创建
     * @param idNumber 个人身份证号
     * @param name 个人姓名
     * @param mobile 手机号
     * @return 返回结果
     */
    private SignatureAccount createAccountIfAbsent(String idNumber, String name, String mobile) throws EsignException {
        SignatureAccount signatureAccount = new SignatureAccount();
        try {
            // 创建个人账号
            PersonalAccountCreateRequest pacRequest = PersonalAccountCreateRequest.builder()
                    .thirdPartyUserId(idNumber)
                    .name(name)
                    .idType(EsignConstants.personalIdType.CRED_PSN_CH_IDCARD)
                    .idNumber(idNumber)
                    .build();

            PersonalAccountCreateResponse pacResponse = signApi.account().personalAccountCreate(pacRequest);

            signatureAccount.setAccountId(pacResponse.getAccountId());
            signatureAccount.setName(name);
            signatureAccount.setIdNumber(idNumber);
            signatureAccount.setIdType(EsignConstants.personalIdType.CRED_PSN_CH_IDCARD);
            signatureAccount.setMobile(mobile);
            signatureAccount.setState(CommonBooleanEnum.NO.getCode());
            signatureAccount.setSilent(CommonBooleanEnum.NO.getCode());
        } catch (EsignException e) {
            // 如果接口返回报错,返回码是账户已存在,则查询账户信息
            if (EsignApiCode.ACCOUNT_EXISTS.equals(e.getError().getErrCode())) {
                PersonalAccountDetailResponse padResponse = signApi.account().personalAccountByThirdId(idNumber);
                signatureAccount.setAccountId(padResponse.getAccountId());
                signatureAccount.setName(padResponse.getName());
                signatureAccount.setIdNumber(padResponse.getIdNumber());
                signatureAccount.setIdType(EsignConstants.personalIdType.CRED_PSN_CH_IDCARD);
                signatureAccount.setMobile(padResponse.getMobile());
                signatureAccount.setState(Optional.ofNullable(padResponse.getStatus()).filter(status -> status).map(status -> CommonBooleanEnum.YES.getCode()).orElse(CommonBooleanEnum.NO.getCode()));
            } else {
                // 其他未知异常向上抛
                throw e;
            }
        }

        // 查询个人印章
        SealDetailResponse sealDetailResponse = signApi.seal().personalSealDetail(signatureAccount.getAccountId());
        if (sealDetailResponse.getTotal() > 0) {
            // 有个人印章,则保存
            String sealId = Optional.ofNullable(sealDetailResponse.getSeals()).map(list -> list.get(0).getSealId()).orElse("");
            signatureAccount.setSealId(sealId);
        } else {
            // 没有个人印章,则创建
            PersonalSealCreateRequest personalSealCreateRequest = PersonalSealCreateRequest.builder()
                    .accountId(signatureAccount.getAccountId())
                    .color(EsignConstants.SealColor.RED)
                    .type(EsignConstants.SealPersonalType.SQUARE)
                    .build();
            PersonalSealCreateResponse pscResponse = signApi.seal().personalSealCreate(personalSealCreateRequest);
            signatureAccount.setSealId(pscResponse.getSealId());
        }

        return signatureAccount;
    }

    /**
     * 比较留存信息
     * @param account 个人信息
     * @param name 名称
     * @param mobile 手机号
     * @return 返回结果
     */
    private boolean verifyMessage(SignatureAccount account, String name, String mobile) {
        return account.getName().equals(name)
                && account.getMobile().equals(mobile);
    }
}